"""
FastAPI主应用
提供RESTful API接口
"""
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Dict, Optional
import logging

import sys
from pathlib import Path

# 添加项目根目录到Python路径
sys.path.insert(0, str(Path(__file__).parent.parent))

from retrieval import TextEmbedder, FAISSIndexer
from summarization import RAGSummarizer
from data_collection.data_storage import DataStorage
from evaluation import MetricsEvaluator
from config import FAISS_INDEX_DIR, TOP_K

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI(
    title="医学文献智能检索与摘要平台",
    description="基于大模型的医学文献检索和自动摘要系统",
    version="1.0.0"
)

# CORS配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 初始化组件
embedder = TextEmbedder()
indexer = FAISSIndexer()
storage = DataStorage()
summarizer = RAGSummarizer()
evaluator = MetricsEvaluator()

# 请求模型
class SearchRequest(BaseModel):
    query: str
    top_k: int = TOP_K

class SearchResponse(BaseModel):
    papers: List[Dict]
    summary: str
    query: str

class EvaluationRequest(BaseModel):
    relevant_pmids: List[str]
    retrieved_pmids: List[str]

# API端点
@app.get("/")
async def root():
    """根路径"""
    return {
        "message": "医学文献智能检索与摘要平台 API",
        "version": "1.0.0"
    }

@app.get("/health")
async def health():
    """健康检查"""
    try:
        indexer.load(str(FAISS_INDEX_DIR / "medical_index"))
        return {"status": "healthy"}
    except Exception as e:
        logger.error(f"健康检查失败: {e}")
        raise HTTPException(status_code=500, detail="系统未初始化")

@app.post("/search", response_model=SearchResponse)
async def search_literature(request: SearchRequest):
    """
    搜索医学文献并生成摘要
    
    Args:
        request: 搜索请求
        
    Returns:
        搜索结果和摘要
    """
    try:
        logger.info(f"收到搜索请求: {request.query}")
        
        # 1. 向量化查询
        query_vector = embedder.encode_texts([request.query])
        
        # 2. 加载索引（如果还没有加载）
        try:
            stats = indexer.get_stats()
            if stats["total_vectors"] == 0:
                indexer.load(str(FAISS_INDEX_DIR / "medical_index"))
        except:
            indexer.load(str(FAISS_INDEX_DIR / "medical_index"))
        
        # 3. 检索相似论文
        results = indexer.search_by_vector(query_vector, top_k=request.top_k)
        
        # 4. 获取论文详情
        papers = []
        for result in results:
            pmid = result["pmid"]
            paper = storage.get_paper_by_pmid(pmid)
            if paper:
                paper["relevance_score"] = result["score"]
                papers.append(paper)
        
        # 5. 生成摘要
        summary = summarizer.generate_summary(papers, query=request.query)
        
        return {
            "papers": papers,
            "summary": summary,
            "query": request.query
        }
        
    except Exception as e:
        logger.error(f"搜索失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/papers/{pmid}")
async def get_paper(pmid: str):
    """
    根据PMID获取论文详情
    
    Args:
        pmid: PubMed ID
        
    Returns:
        论文详情
    """
    paper = storage.get_paper_by_pmid(pmid)
    if not paper:
        raise HTTPException(status_code=404, detail="论文未找到")
    return paper

@app.get("/papers")
async def list_papers(limit: int = Query(100, le=1000)):
    """
    列出所有论文
    
    Args:
        limit: 返回数量限制
        
    Returns:
        论文列表
    """
    papers = storage.get_all_papers(limit=limit)
    return {"papers": papers, "total": len(papers)}

@app.post("/evaluate")
async def evaluate_retrieval(request: EvaluationRequest):
    """
    评估检索性能
    
    Args:
        request: 评估请求
        
    Returns:
        评估结果
    """
    try:
        results = evaluator.evaluate_retrieval(
            request.relevant_pmids,
            request.retrieved_pmids,
            k=10
        )
        return results
    except Exception as e:
        logger.error(f"评估失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/stats")
async def get_stats():
    """获取系统统计信息"""
    try:
        paper_count = storage.get_paper_count()
        
        try:
            index_stats = indexer.get_stats()
        except:
            index_stats = {"total_vectors": 0, "error": "Index not loaded"}
        
        return {
            "papers_in_database": paper_count,
            "index_stats": index_stats
        }
    except Exception as e:
        logger.error(f"获取统计信息失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
